package org.batatasframework.support.database.metadatas;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.Types;
import java.text.DecimalFormat;

import org.batatasframework.support.database.DatabaseType;
import org.batatasframework.support.database.FieldEditable;
import org.batatasframework.support.database.TableDescriptor;
import org.batatasframework.support.database.TableInfo;
import org.batatasframework.support.type.JavaType;

import cn.bonoon.kernel.util.StringHelper;

/**
 * <pre>这里是具体的一个数据库的表结构，以后需要添加包括索引在内的更详细的信息；
 * 这样可以对查询条件进行优化，可以统计建索引和没建索引的查询的效率。</pre>
 * 
 * @author jackson
 *
 */
public final class DatabaseTableStructure extends AbstractTableMetadata<FieldMetadata> implements TableMetadata, TableDescriptor{
	
	private TableInfo tableInfo;
	private String primaryKeyMetadata = "C_ID";

	public DatabaseTableStructure(
//			DatabaseMetadataResource databaseMetadataRresource, 
			ResultSet resultSet) throws Exception{
//		super(databaseMetadataRresource);
		init(resultSet);
	}
	
	@Override
	public TableMetadata getTableMetadata() {
		return this;
	}
	
	@Override
	public String getPrimaryKey() {
		return primaryKeyMetadata;
	}
	
	public void init(ResultSet rs) throws Exception{
		String catalogName = rs.getString("TABLE_CAT");
		String schemaName = rs.getString("TABLE_SCHEM");
		String tableName = rs.getString("TABLE_NAME");
		this.tableInfo = new TableInfo(schemaName, catalogName, tableName);
		
		//rs.close();
		//initColumns(meta, catalogName, schemaName, tableName);
	}
	
	public void initColumns(DatabaseMetaData meta) throws Exception {
//		ResultSet rs = null;

		try(ResultSet rs = meta.getColumns(
				tableInfo.getCatalogName(),
				tableInfo.getSchemaName(), 
				tableInfo.getSourceName(), "%")) {
//			rs = meta.getColumns(catalogName, schemaName, tableName, "%");
			while ( rs.next() ) {
				addColumn(rs);
			}
		}
//		finally  {
//			if (rs != null) {
//				rs.close();
//				rs = null;
//			}
//		}
		

//		try {
//			rs = meta.getPrimaryKeys(catalog, schema, name);
//			while ( rs.next() ) {
//				String name = rs.getString("COLUMN_NAME");
//				int ordinal = rs.getInt("KEY_SEQ"); 
//				
//			}
//		}
//		finally  {
//			if (rs != null) {
//				rs.close();
//				rs = null;
//			}
//		}
	}

	public void addColumn(ResultSet rs) throws Exception {
		String column = rs.getString("COLUMN_NAME");

		if (column==null) {
			return;
		}

		columns.put(column, new DatabaseFieldMetadata(this, rs));
	}
	
	public FieldMetadata getColumn(String columnName){
		return columns.get(columnName);
	}
	
	@Override
	public TableInfo getTableInfo() {
		return tableInfo;
	}

	@Override
	public String getTableName() {
		return tableInfo.getTableName();
	}
	
	class DatabaseFieldMetadata extends AbstractFieldMetadata<TableMetadata> implements FieldEditable{
		private final String name;
		private final int columnSize;
		private final int nullAble;
		private final int dataType;

		private boolean editable;
		
		DatabaseFieldMetadata(TableMetadata tableMetadata, ResultSet rs) throws Exception{
			super(tableMetadata);
			name = rs.getString("COLUMN_NAME");
			title = rs.getString("REMARKS");
			dataType = rs.getInt("DATA_TYPE");     //对应的java.sql.Types的SQL类型(列类型ID)
			//String dataTypeName = rs.getString("TYPE_NAME");  //java.sql.Types类型名称(列类型名称)
			columnSize = rs.getInt("COLUMN_SIZE");  //列大小
			int decimalDigits = rs.getInt("DECIMAL_DIGITS");  //小数位数
			 /**
	         *  0 (columnNoNulls) - 该列不允许为空
	         *  1 (columnNullable) - 该列允许为空
	         *  2 (columnNullableUnknown) - 不确定该列是否为空
	         */
	        nullAble = rs.getInt("NULLABLE");  //是否允许为null  
	        //String columnDef = rs.getString("COLUMN_DEF");  //默认值 
	        //int charOctetLength = rs.getInt("CHAR_OCTET_LENGTH");    // 对于 char 类型，该长度是列中的最大字节数
	        ordinal = rs.getInt("ORDINAL_POSITION"); 
	        
	        if(decimalDigits > 0){
	        	StringBuffer buffer = new StringBuffer(decimalDigits + 2);
	        	buffer.append("#.");
	        	for(int i = 0; i < decimalDigits; i++) buffer.append('0');
	        	this.format = new DecimalFormat(buffer.toString());
	        }
		}
		
		@Override
		public boolean isEditable() {
			return editable;
		}

		public String getName() {
			return name;
		}
		@Override
		public String getcolumnName() {
			return name;
		}
		@Override
		public void setJavaType(JavaType javaType) {
			// TODO Auto-generated method stub
			
		}

		private DatabaseType databaseType;
		
		/**
		 * 对应的java.sql.Types的SQL类型(列类型ID)
		 * @return
		 */
		public DatabaseType getDataType() {
			if(null == databaseType){
				switch (dataType) {
				case Types.VARCHAR:
				case Types.CHAR:
				case Types.NVARCHAR:
				case Types.NCHAR:
					databaseType = DatabaseType.STRING;
					break;
				case Types.INTEGER:
				case Types.BIGINT:
				case Types.SMALLINT:
					databaseType = DatabaseType.NUMBER;
					break;
				case Types.DOUBLE:
				case Types.FLOAT:
					databaseType = DatabaseType.DECIMAL;
					break;
				case Types.DATE:
					databaseType = DatabaseType.DATE;
					break;
				case Types.TIME:
					databaseType = DatabaseType.TIME;
					break;
				case Types.TIMESTAMP:
					databaseType = DatabaseType.TIMESTAMP;
					break;
				case Types.BOOLEAN:
				case Types.BIT:
					databaseType = DatabaseType.BOOLEAN;
					break;
				default:
					databaseType = DatabaseType.OBJECT;
					break;
				}
			}
			return databaseType;
		}
		
		public int getColumnSize() {
			return columnSize;
		}

		public int getNullAble() {
			return nullAble;
		}

		/**
		 * 是否有定义字段的备注信息，如果有，则可以认为是默认的用于显示的字段
		 * @return
		 */
		@Override
		public boolean enabled(){
			return StringHelper.isNotEmpty(title);
		}
	}

}
